package com.hulang.sms.sending.service;

import com.google.gson.Gson;
import com.hulang.sms.sending.bean.*;
import com.hulang.sms.sending.mapper.AliYunSmsPlatformMapper;
import com.hulang.sms.sending.mapper.SendHistoryMapper;
import com.hulang.sms.sending.mapper.SysParamMapper;
import com.hulang.sms.sending.utils.AliyunSmsUtils;
import com.hulang.sms.sending.utils.DateUtil;
import com.hulang.sms.sending.utils.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class SendingService {

    @Autowired
    AliYunSmsPlatformMapper aliYunSmsPlatformMapper;

    @Autowired
    SendHistoryMapper sendHistoryMapper;

    @Autowired
    SysParamMapper sysParamMapper;

    /**
     * 请求成功
     */
    private static final String ALIYUN_SMS_RESULT_CODE_OK = "OK";
    /**
     * RAM权限DENY
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISP_RAM_PERMISSION_DENY = "isp.RAM_PERMISSION_DENY";
    /**
     * 业务停机
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_OUT_OF_SERVICE = "isv.OUT_OF_SERVICE";
    /**
     * 未开通云通信产品的阿里云客户
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_PRODUCT_UN_SUBSCRIPT = "isv.PRODUCT_UN_SUBSCRIPT";
    /**
     * 产品未开通
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_PRODUCT_UNSUBSCRIBE = "isv.PRODUCT_UNSUBSCRIBE";
    /**
     * 账户不存在
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_ACCOUNT_NOT_EXISTS = "isv.ACCOUNT_NOT_EXISTS";
    /**
     * 账户异常
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_ACCOUNT_ABNORMAL = "isv.ACCOUNT_ABNORMAL";
    /**
     * 短信模板不合法
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_SMS_TEMPLATE_ILLEGAL = "isv.SMS_TEMPLATE_ILLEGAL";
    /**
     * 短信签名不合法
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_SMS_SIGNATURE_ILLEGAL = "isv.SMS_SIGNATURE_ILLEGAL";
    /**
     * 参数异常
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_INVALID_PARAMETERS = "isv.INVALID_PARAMETERS";
    /**
     * 系统错误
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISP_SYSTEM_ERROR = "isp.SYSTEM_ERROR";
    /**
     * 非法手机号
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_MOBILE_NUMBER_ILLEGAL = "isv.MOBILE_NUMBER_ILLEGAL";
    /**
     * 手机号码数量超过限制
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_MOBILE_COUNT_OVER_LIMIT = "isv.MOBILE_COUNT_OVER_LIMIT";
    /**
     * 模板缺少变量
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_TEMPLATE_MISSING_PARAMETERS = "isv.TEMPLATE_MISSING_PARAMETERS";

    /**
     * 业务限流
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_BUSINESS_LIMIT_CONTROL = "isv.BUSINESS_LIMIT_CONTROL";
    /**
     * JSON参数不合法，只接受字符串值
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_INVALID_JSON_PARAM = "isv.INVALID_JSON_PARAM";

    /**
     * 黑名单管控
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_BLACK_KEY_CONTROL_LIMIT = "isv.BLACK_KEY_CONTROL_LIMIT";

    /**
     * 参数超出长度限制
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_PARAM_LENGTH_LIMIT = "isv.PARAM_LENGTH_LIMIT";

    /**
     * 不支持URL
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_PARAM_NOT_SUPPORT_URL = "isv.PARAM_NOT_SUPPORT_URL";

    /**
     * 账户余额不足
     */
    private static final String ALIYUN_SMS_RESULT_CODE_ISV_AMOUNT_NOT_ENOUGH = "isv.AMOUNT_NOT_ENOUGH";

    /**
     * 发生异常
     */
    private static final String HAPPEN_EXCEPTION = "happen_exception";


    /**
     * 验证码
     */
    private static final int TEMPLATE_TYPE_VERIFICATION_CODE = 1;
    /**
     * 短信通知
     */
    private static final int TEMPLATE_TYPE_NOTICE = 2;
    /**
     * 推广短信
     */
    private static final int TEMPLATE_TYPE_EXTENSION = 3;
    /**
     * 单个手机单日次数限制上限 singlePhoneOneDayFrequencyUpperLimit 默认8条
     */
    private static final int SINGLE_PHONE_ONEDAY_FREQUENCY_UPPERLIMIT = 8;

    /**
     * 单个ip单日次数限制上限 singleIpOneDayFrequencyUpperLimit 默认20条
     */
    private static final int SINGLE_IP_ONEDAY_FREQUENCY_UPPERLIMIT = 20;

    /**
     * 开启平台短信发送频次限制开关 openLimitSwitch 1打开 0关闭 默认打开
     */
    private static final int OPEN_LIMIT_SWITCH = 1;

    /**
     * 手机号格式正则表达式
     */
    public final static String phoneRegexp = "^1(([3,5,6,7,8]\\d{9})|(4[5,7]\\d{8})|(7[0,6-8]\\d{8}))$";


    /**
     * 用阿里云短信模板发送短信
     *
     * @param sendParam
     * @param request
     * @return
     */
    public ApiResult smsSendForAliYun(SendParam sendParam, HttpServletRequest request) {
        ApiResult result = new ApiResult();
        String phone = sendParam.getPhone();
        if (!legitimatePhone(phone)) {
            return result.failed("手机号格式错误");
        }

        Integer templateSeq = sendParam.getTemplateSeq();
        AliYunSmsPlatform template = legitimateTemplateSeq(templateSeq);
        if (template == null) {
            return result.failed("阿里云短信模板不存在");
        }
        Integer templateType = template.getTemplateType();

        if (!sendFrequencyUnusual(phone, request)) {
            return result.failed("发送频率过高，发送失败");
        }

        // 添加发送记录
        SendHistory history = addSendHistory(template, sendParam, request);

        if (templateType.intValue() == TEMPLATE_TYPE_VERIFICATION_CODE) {
            result = AliyunSmsUtils.smsSendForAliYunWithVerificationCode(sendParam, template);
        } else if (templateType.intValue() == TEMPLATE_TYPE_NOTICE) {
            result = AliyunSmsUtils.smsSendForAliYunWithNotice(sendParam, template);
        } else if (templateType.intValue() == TEMPLATE_TYPE_EXTENSION) {
            result = result.failed("暂不支持");
        }

        // 更新发送记录
        history = updateSendHistory(history, result);
        result.setData(history.getResultDesc());
        return result;
    }

    /**
     * 更新发送记录
     *
     * @param history
     * @param result
     */
    private SendHistory updateSendHistory(SendHistory history, ApiResult result) {
        String code = result.getInfo();
        switch (code) {
            case ALIYUN_SMS_RESULT_CODE_OK:
                history.setSendResult(1);
                history.setResultDesc("发送成功");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISP_RAM_PERMISSION_DENY:
                history.setSendResult(0);
                history.setResultDesc("RAM权限DENY");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_OUT_OF_SERVICE:
                history.setSendResult(0);
                history.setResultDesc("业务停机");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_PRODUCT_UN_SUBSCRIPT:
                history.setSendResult(0);
                history.setResultDesc("未开通云通信产品的阿里云客户");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_PRODUCT_UNSUBSCRIBE:
                history.setSendResult(0);
                history.setResultDesc("产品未开通");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_ACCOUNT_NOT_EXISTS:
                history.setSendResult(0);
                history.setResultDesc("账户不存在");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_ACCOUNT_ABNORMAL:
                history.setSendResult(0);
                history.setResultDesc("账户异常");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_SMS_TEMPLATE_ILLEGAL:
                history.setSendResult(0);
                history.setResultDesc("短信模板不合法");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_SMS_SIGNATURE_ILLEGAL:
                history.setSendResult(0);
                history.setResultDesc("短信签名不合法");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_INVALID_PARAMETERS:
                history.setSendResult(0);
                history.setResultDesc("参数异常");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISP_SYSTEM_ERROR:
                history.setSendResult(0);
                history.setResultDesc("系统错误");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_MOBILE_NUMBER_ILLEGAL:
                history.setSendResult(0);
                history.setResultDesc("非法手机号");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_MOBILE_COUNT_OVER_LIMIT:
                history.setSendResult(0);
                history.setResultDesc("手机号码数量超过限制");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_TEMPLATE_MISSING_PARAMETERS:
                history.setSendResult(0);
                history.setResultDesc("模板缺少变量");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_BUSINESS_LIMIT_CONTROL:
                history.setSendResult(0);
                history.setResultDesc("业务限流");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_INVALID_JSON_PARAM:
                history.setSendResult(0);
                history.setResultDesc("JSON参数不合法，只接受字符串值");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_BLACK_KEY_CONTROL_LIMIT:
                history.setSendResult(0);
                history.setResultDesc("黑名单管控");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_PARAM_LENGTH_LIMIT:
                history.setSendResult(0);
                history.setResultDesc("参数超出长度限制");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_PARAM_NOT_SUPPORT_URL:
                history.setSendResult(0);
                history.setResultDesc("不支持URL");
                break;
            case ALIYUN_SMS_RESULT_CODE_ISV_AMOUNT_NOT_ENOUGH:
                history.setSendResult(0);
                history.setResultDesc("账户余额不足");
                break;
            case HAPPEN_EXCEPTION:
                history.setSendResult(0);
                history.setResultDesc("内部异常");
                break;
        }
        sendHistoryMapper.updateById(history);

        return history;
    }

    /**
     * 添加发送记录，以便统计发送频率和日后日志查询
     *
     * @param sendParam
     * @param request
     */
    private SendHistory addSendHistory(AliYunSmsPlatform template, SendParam sendParam, HttpServletRequest request) {
        SendHistory history = new SendHistory();
        history.setTemplateSeq(template.getTemplateSeq());
        history.setSendParamStr(new Gson().toJson(sendParam.getParam()));
        history.setSendIp(IpUtil.getIpAddr(request));
        history.setPhone(sendParam.getPhone());
        history.setSendResult(-1);
        history.setSendTm(DateUtil.dateToYMDHMS(new Date()));
        sendHistoryMapper.insert(history);
        return history;
    }

    /**
     * 发送频率检测
     *
     * @param phone
     * @param request
     * @return
     */
    private boolean sendFrequencyUnusual(String phone, HttpServletRequest request) {

        // 开启平台短信发送频次限制开关1打开 0关闭
        SysParam openLimitSwitch = sysParamMapper.getParamByName("openLimitSwitch");
        if (openLimitSwitch != null && "0".equals(openLimitSwitch.getValue())) {// 开关关闭，不用校验
            return true;
        }

        String currentDay = DateUtil.dateToYMD(new Date());
        SumParam sumParam = new SumParam();
        sumParam.setStartTm(currentDay + " 00:00:00");
        sumParam.setEndTm(currentDay + " 23:59:59");

        String ip = IpUtil.getIpAddr(request);
        if (ip != null) {
            sumParam.setSendIp(ip);
            int singleIpOneDaySendNum = sendHistoryMapper.sumSingleIpOneDaySendNum(sumParam);

            // 单个IP单日次数限制上限 singleIpOneDayFrequencyUpperLimitParm
            SysParam singleIpOneDayFrequencyUpperLimitParam = sysParamMapper.getParamByName("singleIpOneDayFrequencyUpperLimit");
            if (singleIpOneDayFrequencyUpperLimitParam == null) {// 使用默认值
                if (singleIpOneDaySendNum > SINGLE_IP_ONEDAY_FREQUENCY_UPPERLIMIT) {
                    return false;
                }
            } else {
                if (singleIpOneDaySendNum > Integer.parseInt(singleIpOneDayFrequencyUpperLimitParam.getValue())) {
                    return false;
                }
            }
        }

        sumParam.setPhone(phone);
        int singlePhoneOneDaySendNum = sendHistoryMapper.sumSinglePhoneOneDaySendNum(sumParam);

        // 单个手机单日次数限制上限 singlePhoneOneDayFrequencyUpperLimitParam
        SysParam singlePhoneOneDayFrequencyUpperLimitParam = sysParamMapper.getParamByName("singlePhoneOneDayFrequencyUpperLimit");
        if (singlePhoneOneDayFrequencyUpperLimitParam == null) {// 使用默认值
            if (singlePhoneOneDaySendNum > SINGLE_PHONE_ONEDAY_FREQUENCY_UPPERLIMIT) {
                return false;
            }
        } else {
            if (singlePhoneOneDaySendNum > Integer.parseInt(singlePhoneOneDayFrequencyUpperLimitParam.getValue())) {
                return false;
            }
        }
        return true;
    }

    /**
     * 短信模板是否存在
     *
     * @param templateSeq
     * @return
     */
    private AliYunSmsPlatform legitimateTemplateSeq(Integer templateSeq) {

        if (templateSeq == null) {
            return null;
        }
        AliYunSmsPlatform template = aliYunSmsPlatformMapper.getAliYunSmsPlatformBySeq(templateSeq);
        if (template == null) {
            return null;
        }
        return template;
    }

    /**
     * 国内各大运营商手机号码段的分配如下：
     * <p>
     * 　　中国移动：134(0-8)、135、136、137、138、139、150、151、152、157(TD)、158、159、182、183、184、187、178、188、147（数据卡号段） 、1705（虚拟运营商移动号段）
     * <p>
     * 　　中国联通：130、131、132、145(数据卡号段)155、156、176、185、186、1709（虚拟运营商联通号段）
     * <p>
     * 　　中国电信：133、153、177、180、181、189、（1349卫通）、1700（虚拟运营商电信号段）
     *
     * @param phone
     * @return
     */
    private boolean legitimatePhone(String phone) {

        if (null == phone || "".equalsIgnoreCase(phone)) {

            return false;
        } else {
            if (phone.length() != 11) {
                return false;
            }

            Pattern p = Pattern.compile(phoneRegexp);
            Matcher m = p.matcher(phone);
            boolean isMatch = m.matches();
            if (!isMatch) {
                return false;
            }
        }
        return true;
    }
}
